﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using Newtonsoft.Json;
using System.ComponentModel;

namespace WpfBeyond
{
    [JsonObject(MemberSerialization.OptIn)]
    public class Device : INotifyPropertyChanged
    {
        public string ipaddr = "";
        public int port = 0;

        public string serialNo = "";    /*13位序列号*/
        public string Software = "";    /*软件版本*/
        public string Hardware = "";    /*硬件版本*/

        public DateTime Server_reqtime = DateTime.MinValue;//请求平台信息时间

        public string device_type;	    /*终端类型*/

        private string resource_code;

        //public string area_name;    /*区域名称*/
        /*终端逻辑地址*/
        //public string ctr_code;     /*当前受控制的区域码*/
        //public int audio_pid;       /*音频PID*/

        public Int64 BytesRate = 0; /*接收速率 单位：KB/S*/
        public Int64 recvBytes = 0;

        public DateTime online_time = DateTime.MinValue;//上线时间
        public DateTime last_time;              /*最后心跳时间*/
        //public int heartbeat = 60;             /*心跳超时（秒）*/
        public bool online = true;            /*是否在线,首次添加应该是在线的*/

        private bool m_isCheck = false;
        private string addr = "";

        public string StrStatus
        {
            get
            {
                if (Status == 1) return "空闲";
                else if (Status == 2) return "工作";
                else if (Status == 0) return "离线";
                else return "故障";
            }
        }

        [JsonProperty]
        public string Resource_code { get => resource_code; set => resource_code = value; }
        [JsonProperty]
        public string SerialNo { get => serialNo; set => serialNo = value; }
        public EndPoint IP { get => socket.RemoteEndPoint; }
        public bool IsCheck
        {
            get => m_isCheck;
            set
            {
                if (m_isCheck != value)
                {
                    m_isCheck = value;
                }
            }
        }

        [JsonProperty]
        public string Addr { get => addr; set { addr = value; OnPropertyChanged("Addr"); } }
        [JsonProperty]
        public int Status { get => status; set { status = value; OnPropertyChanged("StrStatus"); } }
        [JsonProperty]
        public string Local_ip { get => local_ip; set => local_ip = value; }
        [JsonProperty]
        public string Local_mask { get => local_mask; set => local_mask = value; }
        [JsonProperty]
        public string Local_gw { get => local_gw; set => local_gw = value; }

        public int errCode;//故障代码

        //public string GSM_mysysinfo = "0,00";    /*$MYSYSINFO信息*/
        //public int SignalStrength = 0;	/*当前模式下信号强度*/
        //public DateTime GSM_reqtime = DateTime.MinValue;
        //public DateTime GSM_updatetime = DateTime.MinValue;

        //public int voltage;	           /* 电压*/
        //public int power_current;    /*功放电流*/
        public int volume;          /*广播音量大小*/

        //本地地址
        private string local_ip;
        private string local_mask;
        private string local_gw;

        //回传方式
        public Byte reback_type;
        public string reback_param;

        private int status = 0;
        public int reg = 0;

        public double process_ms = 0;

        public int ThreadCount = 0;     /*运行的线程数量*/

        public int child_port;          /*下属终端上报端口*/
        public Devices child_devices = new Devices();   /*下属终端*/

        public int child_online_num = 0;    /*在线终端数*/
        public int child_offline_num = 0;   /*离线终端数*/

        public int recv_type = -1;/*0:日常广播 1：应急广播 -1：无*/

        public string run_time = "";/*运行时长*/

        public int ReStart_times = 0;
        public DateTime ReStart_dateTimes = DateTime.MinValue;

        public object _lock_user = new object();/*控制用户锁*/
        public string lock_user = "";/*如果不为空，就是被这个用户锁定了*/

        public Socket socket = null;//设备D协议长连接的句柄

        public List<Socket> child_socket = new List<Socket>();/*心跳TCP连接的SOCKET*/

        public List<TaskInfo> tasklist = new List<TaskInfo>();

        public List<Byte> ReflashTagList = new List<byte>();//刷新的参数标识

        public Device()
        {
            online_time = DateTime.Now;
        }


        public Socket socket_listen = null;

        UInt16 count_CRC(byte[] add, int num)
        {
            UInt16 CRC = 0xFFFF;
            short i;
            short pos = 0;
            while (num > 0)
            {
                CRC ^= add[pos];//*addr++;
                pos++;
                for (i = 0; i < 8; i++)
                {
                    if ((CRC & 1) > 0)
                    {
                        CRC >>= 1;
                        CRC ^= 0xA001;
                    }
                    else
                    {
                        CRC >>= 1;
                    }
                }
                num--;
            }
            return CRC;
        }

        private string ParseValue(byte[] b, int pos, int len)
        {
            int i = 0;
            StringBuilder sb = new StringBuilder();
            for (i = 0; i < len; i++)
            {
                sb.Append(b[i + pos].ToString("X2"));
            }
            return sb.ToString();
        }

        public TaskInfo GetTaskInfo(string ebmid)
        {
            int Index = 0;

            lock (thisLock)
            {
                for (Index = tasklist.Count - 1; Index >= 0; Index--)
                {
                    if (tasklist[Index] == null) break;

                    if (tasklist[Index].Ebmid_str == ebmid)
                    {
                        return tasklist[Index];
                    }
                }
            }
            return null;
        }

        public object thisLock = new object();
        public object childLock = new object();

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }



    public class Devices
    {
        public static object _lock = new object();

        public static List<Device> list = new List<Device>();

        public static bool Add_Device(Device d)//wangm:2020-6-2
        {
            //bool bFlag = false;
            int Index = 0;

            string sn = d.serialNo;

            lock (_lock)
            {
                for (Index = list.Count - 1; Index >= 0; Index--)
                //foreach (Device de in this)
                {
                    if (list[Index] == null) break;

                    //保存在文件中的设备数据不记录IPADDR 和PORT
                    if (list[Index].ipaddr == "" && list[Index].port == 0)
                    {
                        //序列号相同，则覆盖IP地址
                        if (list[Index].SerialNo == d.SerialNo)
                        {
                            list[Index].ipaddr = d.ipaddr;
                            list[Index].port = d.port;
                        }
                    }

                    /*IP信息唯一*/
                    if (list[Index].ipaddr == d.ipaddr
                        && list[Index].port == d.port)
                    {
                        list[Index].last_time = DateTime.Now;

                        /*更新数据*/

                        if (d.serialNo != "0000000000000")
                        {
                            list[Index].serialNo = d.serialNo;
                        }
                        //this[Index].Software = software;
                        list[Index].Resource_code = d.Resource_code;
                        list[Index].socket = d.socket;

                        /*上线状态改变，方便外部提示上线*/
                        if (list[Index].online == false)
                        {
                            list[Index].online = true;
                            LogHelp.Info("[" + d.ipaddr.ToString() + ":" + d.port.ToString() + "]【上线】 序列号:" + d.serialNo);
                            return true;
                        }
                        else if (list[Index].Status != d.Status)
                        {
                            list[Index].Status = d.Status;
                            list[Index].ReflashTagList.Add(0x6);//添加状态刷新标记
                            return true;
                        }
                        else
                        {
                            list[Index].online = true;
                            return false;
                        }
                    }
                }

                list.Add(d);
            }
            return true;
        }

        public static bool Update_Device(Device d)
        {
            //bool bFlag = false;
            int Index = 0;

            string sn = d.serialNo;

            lock (_lock)
            {
                for (Index = list.Count - 1; Index >= 0; Index--)
                //foreach (Device de in this)
                {
                    if (list[Index] == null) break;

                    //资源编码相同
                    if (list[Index].Resource_code == d.Resource_code)
                    {
                        list[Index].last_time = DateTime.Now;

                        /*更新数据*/
                        list[Index].volume = d.volume;
                    }
                }
            }
            return true;
        }


        public static void Remove_Devices(Device d)
        {
            lock (_lock)
            {
                d = list.Find(o => o == d);
                if (d == null)
                {
                    return;
                }

                list.Remove(d);
            }
        }

        public static Device Get_Device(string sn)
        {
            int Index = 0;

            lock (_lock)
            {
                for (Index = list.Count - 1; Index >= 0; Index--)
                {
                    if (list[Index] == null) break;

                    if (list[Index].serialNo == sn)
                        return list[Index];
                }
            }

            return null;
        }

        public static Device Get_Device_byCode(string src_code)
        {
            int Index = 0;

            lock (_lock)
            {
                for (Index = list.Count - 1; Index >= 0; Index--)
                {
                    if (list[Index] == null) break;

                    if (list[Index].Resource_code == src_code)
                        return list[Index];
                }
            }

            return null;
        }

    }


}
